package com.hly.musicbackground.model.user.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hly.musicbackground.Enum.UserLogEnum;
import com.hly.musicbackground.Utils.DateUtils;
import com.hly.musicbackground.Utils.DozerUtils;
import com.hly.musicbackground.Utils.RequestContextUtils;
import com.hly.musicbackground.dao.UserDao;
import com.hly.musicbackground.dao.UserLogDao;
import com.hly.musicbackground.domain.UserLog;
import com.hly.musicbackground.model.admin.VO.ActiveStatisticsVO;
import com.hly.musicbackground.model.admin.VO.ActiveUserLogVO;
import com.hly.musicbackground.model.admin.VO.UserLogVO;
import com.hly.musicbackground.model.user.service.UserLogService;
import com.hly.musicbackground.result.Token;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Log4j2
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserLogServiceImpl extends ServiceImpl<UserLogDao, UserLog> implements UserLogService {

    private final UserDao userDao;
    private final DozerUtils dozerUtils;

    @Override
    public boolean addLog(int uid, int link, String userLogType, String describe) {
        UserLog userLog = new UserLog();
        userLog.setUserId(uid);
        userLog.setLink(link);
        userLog.setUserLogType(userLogType);
        userLog.setLogDescribe(describe);
        return save(userLog);
    }

    @Override
    public boolean addLog(int uid, int link, UserLogEnum logEnum, String describe) {
        return addLog(uid, link, logEnum.getValue(), logEnum.getStr() + describe);
    }

    @Override
    public boolean addUserLogOrFail(int link, String userLogType, String describe) {
        Token token = RequestContextUtils.getToken();
        if (token == null){
            return false;
        }
        return addLog(token.getId(), link, userLogType, describe);
    }

    @Override
    public boolean addUserLogOrFail(int link, UserLogEnum logEnum, String describe) {
        return addUserLogOrFail(link, logEnum.getValue(), logEnum.getStr() + describe);
    }

    @Override
    public boolean addUserLogOrFail(UserLogEnum logEnum, String describe) {
        return addUserLogOrFail(0, logEnum.getValue(), logEnum.getStr() + describe);
    }

    @Override
    public boolean addUserLogOrFail(UserLogEnum logEnum) {
        return addUserLogOrFail(logEnum, "");
    }

    @Override
    @Scheduled(cron = "0 0 12 * * ?")
    public void calmTimeDelete() {
        log.info("正在删除一年以前的日志");
        remove(Wrappers.<UserLog>lambdaQuery().lt(UserLog::getCreateTime, DateUtils.currentTimeSubtract(31104000000L)));
    }

    @Override
    public List<ActiveUserLogVO> getActiveUserList(int day, int month, int limit) {
        List<UserLog> list = list(Wrappers.<UserLog>query()
                .select("user_id,count(1) as user_log_id")
                .last("limit 0," + limit)
                .lambda()
                .lt(UserLog::getCreateTime, DateUtils.ZeroTime(0, 0, 0))
                .gt(UserLog::getCreateTime, DateUtils.ZeroTime(0, month, day))
                .groupBy(UserLog::getUserId));

        List<ActiveUserLogVO> collect = list.stream().map(n -> ActiveUserLogVO.builder().userId(n.getUserId())
                    .name(userDao.selectById(n.getUserId()).getUserName())
                    .value(n.getUserLogId()).build()
        ).collect(Collectors.toList());

        return collect;
    }

    @Override
    public List<UserLogVO> getRecentLogList(int page, int limit, int uid) {
        List<UserLog> records = lambdaQuery().orderByDesc(UserLog::getCreateTime)
                .eq(uid != 0, UserLog::getUserId, uid)
                .page(new Page<>(page, limit)).getRecords();
        List<UserLogVO> convert = dozerUtils.convert(records, UserLogVO.class);

        if(uid == 0){
            convert.forEach(n -> n.setUser(userDao.selectById(n.getUserId())));
        }
        return convert;
    }

    @Override
    public ActiveStatisticsVO getDateActive(int i, boolean b) {
        ActiveStatisticsVO activeStatisticsVO = new ActiveStatisticsVO();
        activeStatisticsVO.setDate(new ArrayList<>());
        activeStatisticsVO.setActiveNumber(new ArrayList<>());
        for (; i > 0; i--) {
            Date dateMin = null;
            Date dateMax = null;
            if (b){
                dateMin = DateUtils.ZeroTime(0, i, 0);
                dateMax = DateUtils.ZeroTime(0, i - 1, 0);
                activeStatisticsVO.getDate().add(DateUtils.dateToString(dateMin, "yyyy/MM"));
            }else {
                dateMin = DateUtils.ZeroTime(0, 0, i);
                dateMax = DateUtils.ZeroTime(0, 0, i - 1);
                activeStatisticsVO.getDate().add(DateUtils.dateToString(dateMin, "MM/dd"));
            }
            activeStatisticsVO.getActiveNumber()
                    .add(lambdaQuery()
                            .lt(UserLog::getCreateTime, dateMax)
                            .gt(UserLog::getCreateTime, dateMin)
                            .count());
        }
        return activeStatisticsVO;
    }

}
